﻿#ifndef _ArchiveManager_H__
#define _ArchiveManager_H__

#include "kernel/OgrePlatform.h"
#include "kernel/string_def.h"
#include "kernel/threading/mutex.h"
#include "kernel/OgreIteratorWrapper.h"

namespace FD
{
	namespace Kernel
	{
		class ArchiveFactory;
		class Archive;
		/// <summary> This class manages the available ArchiveFactory plugins. </summary>
		class FD_Kernel_Export ArchiveManager :  public FD::Kernel::CReferenced
		{
		public:
			typedef std::map<String, FD::Kernel::ArchiveFactory*> ArchiveFactoryMap;
			typedef std::map<String, FD::Kernel::Archive*> ArchiveMap;

		private:
			static FD::Kernel::ArchiveManager *ms_Singleton;
		protected:
			FD::Kernel::Mutex mMutex;

			//// Factories available to create archives, indexed by archive type (String identifier e.g. 'Zip')
			ArchiveFactoryMap mArchFactories;
			//// Currently loaded archives

			FD::Kernel::ArchiveManager::ArchiveMap mArchives;

		public:
			/// <summary> Default constructor - should never get called by a client app.</summary>
			/// <param></param>
			/// <returns></returns>
			ArchiveManager();

			virtual ~ArchiveManager();
			static FD::Kernel::ArchiveManager &getSingleton();
			static FD::Kernel::ArchiveManager *getSingletonPtr();
			/// <summary> Opens an archive for file reading.
			///     @remarks
			///       extension libraries.
			///</summary>
			///   <param> name ="filename" The filename that will be opened</param>
			///   <param> name = "refLibrary"The library that contains the data-handling code</param>
			///   <returns>
			///   If the function succeeds, a valid pointer to an FD::Kernel::Archive
			///  object is returned.
			///</returns>
			FD::Kernel::Archive *load( const String& filename, const String& archiveType, bool readOnly);
			///<summary> Unloads an archive.
			/// remarks
			///	You must ensure that this archive is not being used before removing it.
			/// </summary>
			///<param> name = "arch" </param>
			/// <returns></returns>
			void unload(FD::Kernel::Archive *arch);
			/// <summary>Unloads an archive by name.
			/// remarks
			///	You must ensure that this archive is not being used before removing it.
			/// </summary>
			/// <param>name= "filename"</param>
			///<returns></returns>
			void unload(const String &filename);

			typedef MapIterator<FD::Kernel::ArchiveManager::ArchiveMap> ArchiveMapIterator;
			typedef std::pair<String, FD::Kernel::Archive *> ArchiveMapPair;
			//typedef MapIterator<ArchiveMap> ArchiveMapIterator;

			/// <summary> Get an iterator over the Archives in this Manager. </summary>
			///<param></param>
			/// <returns>FD::Kernel::ArchiveManager::ArchiveMapIterator</returns>
			FD::Kernel::ArchiveManager::ArchiveMapIterator getArchiveIterator();
			/// <summary> Adds a new FD::Kernel::ArchiveFactory to the list of available factories.
			///   remarks
			///       CPlugin developers who add new archive codecs need to call
			///       this after defining their ArchiveFactory subclass and
			///       Archive subclasses for their archive type.
			/// </summary>
			/// <param>name = "factory"</param>
			/// <returns></returns>
			void addArchiveFactory(FD::Kernel::ArchiveFactory *factory);
		};
	}
}

#endif

